home *** CD-ROM | disk | FTP | other *** search
/ Gekkan Dennou Club 145 / Gekkan Dennou Club - 2000.6 Vol. 145 (Japan).7z / Gekkan Dennou Club - 2000.6 Vol. 145 (Japan) (Track 1).bin / docs / asm / asmtime.doc next >
Text File  |  2000-05-08  |  7KB  |  274 lines

  1. ━───────────────────────────────────
  2.          X680x0アセンブラ講座  ~番外編~
  3.  
  4.           《命令のクロック数を計るプログラム》
  5.  
  6.                 鎌田 誠
  7. ────────────────────────────────────
  8.  
  9.  Motorola のマニュアルに書いてある命令のクロック数を検証するには、自分
  10.  
  11. でプログラムを書いて実際に所要時間を調べるのが一番確実です。その具体例を
  12.  
  13. 紹介します。
  14.  
  15.  
  16. ━───────────────────────────────────
  17.  
  18.     _optime
  19.  
  20. ────────────────────────────────────
  21.  
  22. ● _optime とは
  23.  
  24.  サブルーチン _optime は、指定されたサブルーチンを呼び出して帰ってくる
  25.  
  26. までの時間を計るプログラムです。タイマーを 2 本使って 1μs(0.000001 秒)
  27.  
  28. 単位で最大 12799μs(0.012799 秒)まで計ることができます。これを越えると
  29.  
  30. 正しい結果が得られません。
  31.  
  32.  10MHz の 1 クロックは 0.1μs なので、命令 1 個の時間を直接計ることはで
  33.  
  34. きません。12799μs 以内でなるべく多く繰り返して、全体の所要時間を繰り返
  35.  
  36. した回数で割ることで 1 回あたりの所要時間を求めます。なお、結果には命令
  37.  
  38. を繰り返すために使用される分岐命令の所要時間も含まれます。また、呼び出し
  39.  
  40. に必要な jsr/rts の所要時間も含まれるので、なるべく多く繰り返した方が正
  41.  
  42. 確な値が求まります。
  43.  
  44.  
  45. ● _optime の呼び出し方
  46.  
  47.  _optime は Timer-C と Timer-D を使います。これらのタイマーを標準以外の
  48.  
  49. 目的で使用している場合は正常に動作しません。
  50.  
  51.  _optime は必ずスーパーバイザモードで呼び出さなければなりません。
  52.  
  53.  _optime の呼び出し方は次のようになっています。
  54.  
  55.       ┌────────────────────────────────
  56.       │    move.l    #count,-(sp)    ;初期化ルーチンのパラメータ(ループ回数など)
  57.       │    pea.l    op_tini        ;後始末ルーチン(不要ならば0)
  58.       │    pea.l    op_init        ;初期化ルーチン(不要ならば0)
  59.       │    pea.l    op_main        ;計測するルーチン
  60.       │    jsr    optime
  61.       │    lea.l    (16,sp),sp
  62.  
  63. 次のような前宣言をすることで C のプログラムから呼び出すこともできます。
  64.  
  65.       ┌────────────────────────────────
  66.       │int optime(void op_main(void), void op_init(int count), void op_tini(void), int count);
  67.  
  68.  
  69. ● _optime の動作
  70.  
  71.  _optime は、op_init(初期化ルーチン)、op_main(計測するルーチン)、
  72.  
  73. op_tini(後始末ルーチン)の順序で 2 回呼び出し、2 回目の op_main の所要
  74.  
  75. 時間だけ計測します。2 回呼び出すのは、計測ルーチンをキャッシュに乗せるた
  76.  
  77. めです。一連の呼び出し(6 回のサブルーチンコール)は割り込みを禁止した状
  78.  
  79. 態で行われます。
  80.  
  81.  
  82. ●レジスタの扱いについて
  83.  
  84.  op_init では op_main で使用するレジスタの準備をして下さい。optime の 4
  85.  
  86. 番目の引数(count)が op_init に渡されるので、これをレジスタに設定するな
  87.  
  88. どします。メモリを確保するといった大掛かりな処理も可能ですが、割り込みが
  89.  
  90. 禁止されているのでディスクのアクセスなどはできません。op_init で設定され
  91.  
  92. たレジスタは d0-d7/a0-a5 の内容がそのまま op_main に渡されます。
  93.  
  94.  op_main では d0-d7/a0-a6 をすべて使えます。ただし、_optime が op_main
  95.  
  96. を呼び出すときに jsr (a6) として a6 レジスタを使用しているので、a6 レジ
  97.  
  98. スタは op_init から引き継ぐことができません。
  99.  
  100.  op_tini は後始末です。通常は不要でしょう。op_init でメモリを確保したと
  101.  
  102. きは必ずここで開放して下さい。
  103.  
  104.  
  105. ◎ optime.s を見る    TYPE=DOC:optime.s
  106.  
  107.  
  108. ━───────────────────────────────────
  109.  
  110.     メインルーチン
  111.  
  112. ────────────────────────────────────
  113.  
  114.  _optime はサブルーチンなので、これを実行するにはメインルーチンが必要で
  115.  
  116. す。
  117.  
  118.  計測対象のルーチンを _op_init、_op_main、_op_tini という名前で呼び出す
  119.  
  120. メインルーチンを用意しました。コマンドラインでループ回数(op_init の引数)
  121.  
  122. を指定することができます。このソースだけ C で書いてあります。
  123.  
  124.  
  125. ◎ main.c を見る    TYPE=DOC:main.c
  126.  
  127.  
  128. ━───────────────────────────────────
  129.  
  130.     具体例(その1)
  131.  
  132. ────────────────────────────────────
  133.  
  134.  NOP+SUBQ.L #xx,Dn+Bcc.S の所要クロック数を調べます。
  135.  
  136.  NOP は 68000 では 4 クロック、68030 では 2 クロック、68060 では 9 クロ
  137.  
  138. ックの命令です。
  139.  
  140.  SUBQ.L #xx,Dn は 68000 では 8 クロック、68030 では 2 クロック、68060
  141.  
  142. では 1 クロックの命令です。
  143.  
  144.  Bcc.S は 68000 では 10 クロック、68030 では 6 クロック、68060 では 0
  145.  
  146. クロック(分岐予測あり)です。
  147.  
  148.  
  149. ●ソース
  150.  
  151.       ┌────────────────────────────────
  152.      1│;nop+subq.l+bcc.s
  153.      2│    .text
  154.      3│    .even
  155.      4│_op_init::
  156.      5│    move.l    (4,sp),d0
  157.      6│    rts
  158.      7│
  159.      8│    .even
  160.      9│_op_tini::
  161.     10│    rts
  162.     11│
  163.     12│    .align    16
  164.     13│_op_main::
  165.     14│                ;    000    030    060
  166.     15│@@:    nop            ;    4    0-2-0    9
  167.     16│    subq.l    #1,d0        ;    8    2-0-0    1
  168.     17│    bne.s    @b        ;    10    6-0-0    0
  169.     18│                ;    =22    =10    =10
  170.     19│    rts
  171.     20│
  172.     21│_op_name::
  173.     22│    .dc.b    'nop',0
  174.  
  175.  
  176. ●結果
  177.  
  178. ・X68000XVI 10MHz での結果
  179.     [nop]  total=11313(μs)  count=5000  each=2.2626(μs)  each=22.626(clock/10MHz)
  180.  
  181. ・X68000XVI 16MHz での結果
  182.     [nop]  total=10694(μs)  count=8000  each=1.3368(μs)  each=22.2796(clock/16.667MHz)
  183.  
  184. ・X68000XVI 24MHz(REDZONE)での結果
  185.     [nop]  total=9191(μs)  count=10000  each=0.9191(μs)  each=22.0584(clock/24MHz)
  186.  
  187. ・X68030 での結果
  188.     [nop]  total=8000(μs)  count=20000  each=0.4(μs)  each=10(clock/25MHz)
  189.  
  190. ・X68030+060turbo での結果
  191.     [nop]  total=10000(μs)  count=50000  each=0.2(μs)  each=10(clock/50MHz)
  192.  
  193.  
  194. ●補足
  195.  
  196.  68060 のクロック数が多いのは、NOP 命令がパイプラインを掃除するための命
  197.  
  198. 令だからです。コードにパッチを当てるときに隙間を埋めるためには
  199.  
  200. MOVEA.L A0,A0 を使います。
  201.  
  202.  
  203. ━───────────────────────────────────
  204.  
  205.     具体例(その2)
  206.  
  207. ────────────────────────────────────
  208.  
  209.  MULU.W Dn,Dn+SUBQ.L #xx,Dn+Bcc.S の所要クロック数を調べます。
  210.  
  211.  MULU.W Dn,Dn は 68000 では 38~70 クロック、68030 では 28 クロック、
  212.  
  213. 68060 では 2 クロックの命令です。これを確認します。68000 のクロック数は
  214.  
  215. ソースオペランドに含まれる 1 のビットの数に比例しますが、ここではワース
  216.  
  217. トケースの $FFFF で計っています。
  218.  
  219.  MULU.W Dn,Dn 1 回の所要時間が X68000XVI 10MHz で 7μs、060turbo で
  220.  
  221. 0.04μs ですから、ワーストケースで所要時間が 175 倍も違うことがわかりま
  222.  
  223. す。
  224.  
  225.  
  226. ●ソース
  227.  
  228.       ┌────────────────────────────────
  229.      1│;mulu+subq.l+bcc.s
  230.      2│    .text
  231.      3│    .even
  232.      4│_op_init::
  233.      5│    move.l    (4,sp),d0
  234.      6│    move.w    #$FFFF,d1    ;worst case
  235.      7│    rts
  236.      8│
  237.      9│    .even
  238.     10│_op_tini::
  239.     11│    rts
  240.     12│
  241.     13│    .align    16
  242.     14│_op_main::
  243.     15│                ;    000    030    060
  244.     16│@@:    move.w    d1,d2        ;    4    2-0-0    1
  245.     17│    mulu.w    d2,d2        ;    70    2-26-0    2
  246.     18│    subq.l    #1,d0        ;    8    2-0-0    1
  247.     19│    bne.s    @b        ;    10    6-0-0    0
  248.     20│                ;    =92    =38    =4
  249.     21│    rts
  250.     22│
  251.     23│_op_name::
  252.     24│    .dc.b    'mulu',0
  253.  
  254.  
  255. ●結果
  256.  
  257. ・X68000XVI 10MHz での結果
  258. [mulu]  total=9245(μs)  count=1000  each=9.245(μs)  each=92.45(clock/10MHz)
  259.  
  260. ・X68000XVI 16MHz での結果
  261. [mulu]  total=11063(μs)  count=2000  each=5.5315(μs)  each=92.1935(clock/16.667MHz)
  262.  
  263. ・X68000XVI 24MHz(REDZONE)での結果
  264. [mulu]  total=11529(μs)  count=3000  each=3.843(μs)  each=92.232(clock/24MHz)
  265.  
  266. ・X68030 での結果
  267. [mulu]  total=12161(μs)  count=8000  each=1.5201(μs)  each=38.0031(clock/25MHz)
  268.  
  269. ・X68030+060turbo での結果
  270. [mulu]  total=12000(μs)  count=150000  each=0.08(μs)  each=4(clock/50MHz)
  271.  
  272.  
  273. (EOF)
  274.